﻿using System;

namespace NeuralNetwork
{
    class Program
    {
        public static void Main(string[] args)
        {

            Number();
            //NNetwork nn = new NNetwork(10, 5, 3, 0.01);
            //nn.Save("Test");
            //NNetwork nn2 = NNetwork.Load("Test");

            Console.WriteLine(">>>>>>>>>>>程序结束");
            Console.ReadKey();
        }

        private async static void Number()
        {
            //DataSet Set = new DataSet("../../res/train_2500.txt", "../../res/test_100.txt");
            DataSet Set = new DataSet("../../res/mnist_train.csv", "../../res/test_500.txt");

            await Set.PraperSet();

            int inputLength = Set.TrainSet[0].PixelValue.Count;

            NNetwork nn = new NNetwork(inputLength, new int[] { 150 }, 10, 0.05);
            //NNetwork nn = NNetwork.Load("20210628-1437");

            nn.LearningRate = 0.005;
            double successRate = 0; //正确率
            while (successRate < 0.96)
            {
                #region 训练
                for (int trainCount = 0; trainCount < 1; trainCount++)
                {
                    //int trainDataCount = Set.TrainSet.Length;
                    int trainDataCount = 5000;// 这里可有选择只使用训练集的一部分来训练，不然几万条训练数据太恐怖了
                    Random random = new Random((int)(nn.Wight_ho[0, 0] * 100000000));

                    int index = 0;
                    for (int i = 0; i < trainDataCount; i++)
                    {
                        index = random.Next(0, Set.TrainSet.Length);
                        nn.Train(Set.TrainSet[index].PixelValue, Set.TrainSet[index].TrueValue);
                        //Console.WriteLine("Training：{0}/{1}", i, Set.TrainSet.Length);
                    }
                }
                #endregion
                #region 测试
                int success = 0;// 识别成功的
                for (int i = 0; i < Set.TestSet.Length; i++)
                {
                    var result = nn.Query(Set.TestSet[i].PixelValue);

                    // 找出输出中，概率最大的那个值
                    double max = double.MinValue;
                    int index = 0;
                    for (int k = 0; k < result.Count; k++)
                    {
                        if (result[k] > result[index])
                        {
                            index = k;
                            max = result[k];
                        }
                    }

                    // 与真实值进行比对
                    if (/*max > 0.8 &&*/ index == Set.TestSet[i].trueValueIndex)
                    {
                        success++;
                        Console.ForegroundColor = ConsoleColor.Green;
                    }
                    else
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                    }
                    successRate = success * 1.0 / (i + 1);
                    //Console.WriteLine();
                    Console.WriteLine("[{0}/{1}]\tSuccess = {2:F5} %", i + 1, Set.TestSet.Length, successRate * 100);
                    Console.ForegroundColor = ConsoleColor.White;
                }

                if (nn.MaxSuccessRate < successRate) nn.MaxSuccessRate = successRate;
                #endregion
            }

            nn.Save(DateTime.Now.ToString("yyyyMMdd-HHmm"));

            Console.WriteLine("结束");
        }

    }
}
